import logging
import os
import time
from datetime import datetime
from time import sleep
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.common.exceptions import TimeoutException, NoSuchDriverException
from SQ_UI.common.common import *
from selenium import webdriver


class BasePage(object):

    def __init__(self, driver):
        self.driver =  driver

    # 等待元素可见
    def wait_eleVisible(self, filePath, ele_name, timeout=30, poll_frequency=0.5, model=None):
        """
            这是一个自定义等待元素可见的方法
        :param ele_name: 定位属性的K值
        :param filePath: 元素定位的yml文件路径
        :param timeout: 等待的上限时间
        :param poll_frequency: 轮询频率
        :param model: 等待失败时，图片文件中需要表达的功能标注
        :return: None
        """
        get_locator = get_ele_locator(filePath, ele_name)
        logging.info(f"等待{model}元素，定位方式: {get_locator}")
        try:
            start = datetime.now()
            WebDriverWait(self.driver, timeout, poll_frequency).until(EC.visibility_of_element_located(get_locator))
            end = datetime.now()
            logging.info(f"等待{model}时长:{end - start}")
        except TimeoutException:
            logging.exception(f"等待{model}元素失败,定位方式:{get_locator}")
            # 截图
            self.save_webImgs(f"等待元素【{model}】出现异常")
            raise

    # 等待元素不可见
    def wait_ele_NoVisible(self, filePath, ele_name, timeout=30, poll_frequency=0.5, model=None):
        """
            这是一个自定义等待元素不可见的方法
        :param ele_name: 定位属性的K值
        :param filePath: 元素定位的yml文件路径
        :param timeout:等待的上限
        :param poll_frequency:轮询频率
        :param model:等待失败时,截图操作,图片文件中需要表达的功能标注
        :return:None
        """
        get_locator = get_ele_locator(filePath, ele_name)
        logging.info(f'等待"{model}"消失,元素定位:{get_locator}')
        try:
            start = datetime.now()
            WebDriverWait(self.driver, timeout, poll_frequency).until_not(EC.visibility_of_element_located(get_locator))
            end = datetime.now()
            logging.info(f'等待"{model}"时长:{end - start}')
        except TimeoutException:
            logging.exception(f'等待"{model}"元素失败,定位方式:{get_locator}')
            # 截图
            self.save_webImgs(f"等待元素【{model}】消失异常")
            raise

    # 查找一个元素element
    def find_element(self, get_locator):
        """
            查找元素的方法
        :param ele_name: 定位属性的K值
        :param filePath: 元素定位的yml文件路径
        :param model: 查找失败时,截图操作,图片文件中需要表达的功能标注
        :return: 返回查找的元素
        """
        ele = self.driver.find_element(get_locator[0],get_locator[1])
        logging.info(f"查找{ele}元素,元素定位:{get_locator}")
        try:
            return ele
        except NoSuchDriverException:
            logging.exception(f"查找{ele}元素失败,定位方式:{get_locator}")
            # 截图
            self.save_webImgs(f"查找元素【{ele}】异常")
            raise

    # 查找元素集elements
    def find_elements(self, get_locator):
        """
            查找元素的方法
        :param ele_name: 定位属性的K值
        :param filePath: 元素定位的yml文件路径
        :param model: 查找失败时,截图操作,图片文件中需要表达的功能标注
        :return: 返回查找的元素集
        """
        eles = self.driver.find_elements(get_locator[0],get_locator[1])
        logging.info(f"查找{eles}元素集,元素集定位:{get_locator}")
        try:
            return eles
        except NoSuchDriverException:
            logging.exception(f"查找{eles}元素集失败,定位方式:{get_locator}")
            # 截图
            self.save_webImgs(f"查找元素集【{eles}】异常")
            raise

    # 输入操作
    def input_text(self, filePath, ele_name, text):
        """
            文本输入的操作
        :param ele_name: 定位属性的K值
        :param filePath: 元素定位的yml文件路径
        :param text: 输入的具体文本内容
        :param model: 查找失败时,截图操作,图片文件中需要表达的功能标注
        :return: None
        """
        # 查找元素
        ele = self.find_element(get_ele_locator(filePath,ele_name))
        # 输入操作
        logging.info(f"在{ele}输入{text},元素定位:{ele}")
        try:
            ele.send_keys(text)
        except:
            logging.exception(f"{ele}输入操作失败!")
            # 截图
            self.save_webImgs(f"{ele}输入异常")

    # 点击操作
    def click_element(self, filePath, ele_name):
        """
            点击元素的操作
        :param ele_name: 定位属性的K值
        :param filePath: 元素定位的yml文件路径
        :param model: 查找失败时,截图操作,图片文件中需要表达的功能标注
        :return: None
        """
        # 先查找元素在点击
        get_locator = get_ele_locator(filePath,ele_name)
        ele = self.find_element(get_locator)
        # 点击操作
        logging.info(f"点击{ele},元素定位:{get_locator}")
        try:
            ele.click()
        except:
            logging.exception(f"{ele}点击失败")
            # 截图
            self.save_webImgs(f"【{ele}】点击异常")

    # 清除操作
    def clean_inputText(self, filePath, ele_name):
        """
            清除元素的操作
        :param ele_name: 定位属性的K值
        :param filePath: 元素定位的yml文件路径
        :param model: 查找失败时,截图操作,图片文件中需要表达的功能标注
        :return: None
        """
        get_locator = get_ele_locator(filePath, ele_name)
        ele = self.find_element(get_locator)
        # 清除操作
        logging.info(f"清除{ele},元素定位:{get_locator}")
        try:
            ele.clear()
        except:
            logging.exception(f"{ele}清除操作失败")
            # 截图
            self.save_webImgs(f"【{ele}】清除异常")
            raise

    # 获取文本内容
    def get_text(self,filePath, ele_name):
        """
            获取文本内容的操作
        :param ele_name: 定位属性的K值
        :param filePath: 元素定位的yml文件路径
        :param model: 查找失败时,截图操作,图片文件中需要表达的功能标注
        :return: 获取的文本内容
        """

        # 先查找元素在获取文本内容
        get_locator = get_ele_locator(filePath, ele_name)
        ele = self.find_element(get_locator)
        # 获取文本
        logging.info(f"获取{ele}元素文本内容,元素定位:{get_locator}")
        try:
            text = ele.text
            logging.info(f"获取{ele}元素文本内容为【{text}】,元素定位:{get_locator}")
        except:
            logging.exception(f"获取{ele}元素文本内容失败,元素定位:{get_locator}")
            # 截图
            self.save_webImgs(f"获取【{ele}】文本内容异常")
            raise

    # 获取属性值
    def get_element_attribute(self,filePath, ele_name, name):
        """
            获取元素属性值的方法
        :param ele_name: 定位属性的K值
        :param filePath: 元素定位的yml文件路径
        :param name: 元素属性名
        :param model: 查找失败时,截图操作,图片文件中需要表达的功能标注
        :return: 返回元素的属性值
        """
        # 先查找元素在去获取属性值
        get_locator = get_ele_locator(filePath, ele_name)
        ele = self.find_element(get_locator)
        # 获取元素属性值
        logging.info(f'获取"{ele}"元素属性，元素定位:{get_locator}')
        try:
            ele_attribute = ele.get_attribute(name)
            logging.info(f'获取"{ele}"元素"{name}"属性集为"{ele_attribute}"，元素定位:{get_locator}')
            return ele_attribute
        except:
            logging.exception(f'获取"{ele}"元素"{name}"属性失败,元素定位:{get_locator}')
            # 截图
            self.save_webImgs(f"获取[{ele}]属性异常")
            raise

    # iframe 切换
    def switch_iframe(self, frame_refer, timeout=30, poll_frequency=0.5):
        """
            切换iframe的操作
        :param frame_refer: 指定的iframe框架
        :param timeout: 超时上限时间
        :param poll_frequency: 轮询频率
        :param model: 等待失败时,截图操作,图片文件中需要表达的功能标注
        :return: None
        """
        # 等待 iframe 存在
        logging.info('iframe 切换操作:')
        try:
            # 切换 == index\name\id\WebElement
            WebDriverWait(self.driver, timeout, poll_frequency).until(
                EC.frame_to_be_available_and_switch_to_it(frame_refer))
            sleep(0.5)
            logging.info('切换成功')
        except:
            logging.exception('iframe 切换失败!!!')
            # 截图
            self.save_webImgs(f"iframe切换异常")
            raise

    # 窗口切换 = 如果是切换到新窗口,new. 如果是回到默认的窗口,default
    def switch_window(self, name, cur_handles=None, timeout=20, poll_frequency=0.5):
        """
        调用之前要获取window_handles
        :param name: new 代表最新打开的一个窗口. default 代表第一个窗口. 其他的值表示为窗口的 handles
        :param cur_handles:
        :param timeout:等待的上限
        :param poll_frequency:轮询频率
        :param model:等待失败时,截图操作,图片文件中需要表达的功能标注
        :return:
        """
        try:
            if name == 'new':
                if cur_handles is not None:
                    logging.info('切换到最新打开的窗口')
                    WebDriverWait(self.driver, timeout, poll_frequency).until(EC.new_window_is_opened(cur_handles))
                    window_handles = self.driver.window_handles
                    self.driver.switch_to.window(window_handles[-1])
                else:
                    logging.exception('切换失败,没有要切换窗口的信息!!!')
                    self.save_webImgs("切换失败_没有要切换窗口的信息")
                    raise
            elif name == 'default':
                logging.info('切换到默认页面')
                self.driver.switch_to.default_content()
            else:
                logging.info('切换到为 handles 的窗口')
                self.driver.switch_to.window(name)
        except:
            logging.exception('切换窗口失败!!!')
            # 截图
            self.save_webImgs("切换失败_没有要切换窗口的信息")
            raise

    # 截图
    def save_webImgs(self, model=None):
        """
            截图的操作
        :param model: 等待失败时,截图操作,图片文件中需要表达的功能标注
        :return: None
        """
        # filepath = 指图片保存目录/model(页面功能名称)_当前时间到秒.png
        # 截图保存目录
        # 拼接日志文件夹，如果不存在则自动创建
        cur_path = os.path.dirname(os.path.realpath(__file__))
        now_date = time.strftime('%Y-%m-%d', time.localtime(time.time()))
        screenshot_path = os.path.join(os.path.dirname(cur_path), f'Screenshots\\{now_date}')
        if not os.path.exists(screenshot_path):
            os.mkdir(screenshot_path)
        # 当前时间
        dateNow = time.strftime('%Y%m%d_%H%M%S', time.localtime(time.time()))
        # 路径
        filePath = '{}\\{}_{}.png'.format(screenshot_path, model, dateNow)
        try:
            self.driver.save_screenshot(filePath)
            logging.info(f"截屏成功,图片路径为{filePath}")
        except:
            logging.exception('截屏失败!')

    # 退出
    def get_driver(self):
        """
            退出
        :return:
        """
        return self.driver


if __name__ == '__main__':
    pass
    # driver = 1
    # a = BasePage(driver)
    # # a.input_text(r"C:\Users\wuyuaho\PycharmProjects\pythonProject\SQ_UI\config\elementLocators\login_page.yml","username_input","5100000")
    # get_locator = get_ele_locator(r"C:\Users\wuyuaho\PycharmProjects\pythonProject\SQ_UI\config\elementLocators\login_page.yml","username_input")
    # print(a.find_element(get_locator))
